package com.geotmt.billingcenter.modules.statis.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.geotmt.billingcenter.common.entry.CostStatisEntry;
import com.geotmt.billingcenter.common.exception.MyException;
import com.geotmt.billingcenter.common.utils.GeoDateUtils;
import com.geotmt.billingcenter.common.vo.cost.CostHisVo;
import com.geotmt.billingcenter.common.vo.cost.CostStatisVo;
import com.geotmt.billingcenter.common.vo.params.ParamsCost;
import com.geotmt.billingcenter.common.vo.params.RuleVo;
import com.geotmt.billingcenter.modules.cost.service.CostService;
import com.geotmt.billingcenter.modules.designmode.service.RulesStrategy;
import com.geotmt.billingcenter.modules.link.service.LinkService;
import com.geotmt.billingcenter.modules.statis.mapper.CostStatisMapper;
import com.geotmt.billingcenter.modules.statis.service.CostStatisService;
import com.github.pagehelper.PageHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;

/**
 * @Description 成本实现
 * @Author      yanghanwei
 * @Mail        yanghanwei@geotmt.com
 * @Date        2019/4/1 16:09
 * @Version     v1
 **/
@Service
public class CostStatisServiceImpl extends AbstarctService implements CostStatisService {

    private static final Logger logger = LoggerFactory.getLogger(CostStatisServiceImpl.class);

    private static final int BATCH_NUM = 1000;

    @Resource
    private CostStatisMapper costStatisMapper;

    @Resource
    private LinkService linkService;

    @Override
    public List<CostStatisVo> costStatisList(ParamsCost obj) {
        logger.info("成本统计 Service");
        this.insertPage(obj);
        return costStatisMapper.costStatisList(obj);
    }

    @Override
    public CostStatisVo costStatisTotal(ParamsCost obj) {
        logger.info("成本list的总计(最细力度) Service");
        return costStatisMapper.costStatisTotal(obj);
    }

    @Override
    public CostStatisVo hisCostStatis(ParamsCost obj) {
        return costStatisMapper.hisCostStatis(obj);
    }

    @Override
    public int deleteCostStatis(String dayFlag) {
        return costStatisMapper.deleteCostStatis(dayFlag,new Date());
    }

    @Override
    public int deleteCostStatis2(String startDay, String endDay) {
        return costStatisMapper.deleteCostStatis2(startDay, endDay, new Date());
    }

    @Override
    public int updateCostStatis(String startDay, String endDay, Integer id) {
        return costStatisMapper.updateCostStatis(startDay, endDay, id);
    }

    @Override
    public int updateCostMoney(Integer cuserId, String outIfType, String dayFlag, Double money) {
        logger.info("成本更新某天的金额 Service");
        return costStatisMapper.updateCostMoney(cuserId, outIfType, dayFlag, money);
    }

    @Override
    public void batchInsertStatis(List<CostStatisEntry> costStatisList) {
        logger.info("批量插入统计数据 Service");
        int size = costStatisList.size();
        int num = costStatisList.size() / BATCH_NUM  + 1;
        for(int i= 0; i<num; i++){
            // 2 切分并批量插入mysql
            List<CostStatisEntry> subCostStatisList = costStatisList.subList(this.getStartNum(i), this.getEndNum(i, num, size));
            costStatisMapper.batchInsertStatis(subCostStatisList);
        }

    }

    @Async
    @Override
    public void getMoneyAndUpdateCostMoney(CostService costService, CostStatisEntry entry, Date preDay) throws Exception{
        // 1.获取生效规则
        Integer dsId = entry.getDsId();
        Integer outInterfaceId = entry.getOutInterfaceId();
        String outInterfaceType = entry.getOutInterfaceType();
        // 1.1 hive 中没有 outInterfaceId,只能去查一遍
        if((null == outInterfaceId || null == dsId)&& !StringUtils.isEmpty(outInterfaceType)){
            outInterfaceId = linkService.getOutInterfaceIdByType(outInterfaceType);
            dsId = linkService.getDsIdByIfType(outInterfaceType);
        }else{
            throw new MyException("外部接口类型不能为null", HttpServletResponse.SC_NOT_ACCEPTABLE);
        }
        CostHisVo cost = costService.getCost(dsId, outInterfaceId, preDay);
        if(null == cost){
            // TODO
            logger.info("该接口没有配置有效的规则");
            return;
        }
        // 2.计算金额
        RuleVo ruleVo = new RuleVo();
        BeanUtils.copyProperties(cost,ruleVo);
        RulesStrategy rulesStrategy = new RulesStrategy();
        // 2.1.设置标记以及调用量
        ruleVo.setType("cost");
        ruleVo.setCountGet(entry.getCountGet());
        ruleVo.setCountQuery(entry.getCountQuery());
        ruleVo.setCountCharging(entry.getCountCharging());
        Double money = rulesStrategy.getMoney(cost.getFeeFlag(), ruleVo);
        // 3.更新统计的金额
        this.updateCostMoney(entry.getCuserId(), entry.getOutInterfaceType(), GeoDateUtils.getDateStr(preDay, GeoDateUtils.DATE_FORMAT2), money);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getBatchMoneyAndUpdateConsumeMoney(CostService costService, List<CostStatisEntry> costStatisList, Date preDay) throws Exception {
        for (CostStatisEntry entry : costStatisList) {
            // 策略工厂计算消耗金额并更新到mysql
            this.getMoneyAndUpdateCostMoney(costService, entry, preDay);
        }
    }

    /**
     * 添加分页功能
     * @param object
     */
    private void insertPage(ParamsCost object){
        Integer pageNum = object.getPageNum();
        Integer pageSize = object.getPageSize();
        String orderBy = object.getOrderBy();
        if(null != pageNum && null != pageSize){
            PageHelper.startPage(pageNum,pageSize);
        }
        if(!StringUtils.isEmpty(orderBy)){
            PageHelper.orderBy(orderBy);
        }
    }
}
